import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { LevelExperienceEntity } from "../entities/level-experience.entity";

/**
 * 等级经验服务类
 * 提供等级经验相关的业务逻辑
 */
@Injectable()
export class LevelExperienceService {
  constructor(
    @InjectRepository(LevelExperienceEntity)
    private readonly levelExperienceRepository: Repository<LevelExperienceEntity>
  ) {}

  /**
   * 根据等级获取经验值
   * @param level 等级
   * @returns 经验值
   */
  async getExperienceByLevel(level: number): Promise<number | null> {
    const result = await this.levelExperienceRepository.findOne({
      where: { level },
    });
    return result ? result.experience : null;
  }

  /**
   * 根据经验值获取当前等级
   * @param experience 经验值
   * @returns 等级
   */
  async getLevelByExperience(experience: number): Promise<number> {
    const result = await this.levelExperienceRepository
      .createQueryBuilder("le")
      .where("le.experience <= :experience", { experience })
      .orderBy("le.level", "DESC")
      .limit(1)
      .getOne();

    return result ? result.level : 1;
  }

  /**
   * 获取升级到下一级需要的经验值
   * @param currentLevel 当前等级
   * @returns 升级到下一级需要的经验值，如果已经是最高等级则返回null
   */
  async getExpToNextLevel(currentLevel: number): Promise<number | null> {
    const currentLevelData = await this.levelExperienceRepository.findOne({
      where: { level: currentLevel },
    });

    if (!currentLevelData) {
      return null;
    }

    const nextLevelData = await this.levelExperienceRepository.findOne({
      where: { level: currentLevel + 1 },
    });

    if (!nextLevelData) {
      return null; // 已经是最高等级
    }

    return nextLevelData.experience - currentLevelData.experience;
  }

  /**
   * 获取当前等级的经验进度
   * @param currentExperience 当前经验值
   * @returns 经验进度信息
   */
  async getExperienceProgress(currentExperience: number): Promise<{
    currentLevel: number;
    currentLevelExp: number;
    nextLevelExp: number | null;
    expToNext: number | null;
    progress: number; // 0-100的进度百分比
  }> {
    const currentLevel = await this.getLevelByExperience(currentExperience);
    const currentLevelData = await this.levelExperienceRepository.findOne({
      where: { level: currentLevel },
    });

    if (!currentLevelData) {
      throw new Error(`未找到等级 ${currentLevel} 的数据`);
    }

    const nextLevelData = await this.levelExperienceRepository.findOne({
      where: { level: currentLevel + 1 },
    });

    if (!nextLevelData) {
      // 已经是最高等级
      return {
        currentLevel,
        currentLevelExp: currentExperience,
        nextLevelExp: null,
        expToNext: null,
        progress: 100,
      };
    }

    const expToNext = nextLevelData.experience - currentLevelData.experience;
    const currentLevelProgress =
      currentExperience - currentLevelData.experience;
    const progress = Math.min(100, (currentLevelProgress / expToNext) * 100);

    return {
      currentLevel,
      currentLevelExp: currentExperience,
      nextLevelExp: nextLevelData.experience,
      expToNext,
      progress: Math.round(progress * 100) / 100, // 保留两位小数
    };
  }

  /**
   * 获取所有等级数据
   * @returns 所有等级经验数据
   */
  async getAllLevels(): Promise<LevelExperienceEntity[]> {
    return this.levelExperienceRepository.find({
      order: { level: "ASC" },
    });
  }

  /**
   * 获取等级范围数据
   * @param startLevel 起始等级
   * @param endLevel 结束等级
   * @returns 等级范围内的数据
   */
  async getLevelsInRange(
    startLevel: number,
    endLevel: number
  ): Promise<LevelExperienceEntity[]> {
    return this.levelExperienceRepository
      .createQueryBuilder("le")
      .where("le.level >= :startLevel", { startLevel })
      .andWhere("le.level <= :endLevel", { endLevel })
      .orderBy("le.level", "ASC")
      .getMany();
  }

  /**
   * 获取最高等级
   * @returns 最高等级
   */
  async getMaxLevel(): Promise<number> {
    const result = await this.levelExperienceRepository
      .createQueryBuilder("le")
      .select("MAX(le.level)", "maxLevel")
      .getRawOne();

    return result?.maxLevel || 1;
  }

  /**
   * 检查等级是否存在
   * @param level 等级
   * @returns 是否存在
   */
  async levelExists(level: number): Promise<boolean> {
    const count = await this.levelExperienceRepository.count({
      where: { level },
    });
    return count > 0;
  }
}
